/**************************************************************************
/* Anything: a flexible and easy to use data structure and import/export format
/* this is straightforward standalone implementation of ET++ Anything.
/*
/* Copyright (c) 1997 IFA Informatik and Andre Weinand
/*              ,1999 itopia and Marcel Rueedi (rueedi@itopia.ch)
/*
/* Enhanced in   2006 Stefan Tramm
/*
/* This library is free software; you can redistribute it and/or modify
/* it under the terms of the GNU Library General Public License as published 
/* by  the Free Software Foundation; either version 2 of the License or
/* (at your option) any later version.
/*
/* This program is distributed in the hope that it will be useful, but
/* WITHOUT ANY WARRANTY; without even the implied warranty of
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
/* GNU Library General Public License for more details.
/*
/* You should have received a copy of the GNU Library General Public License
/* along with this program; see the file COPYING.LIB.  If not, write to 
/* the Free Software Foundation Inc., 59 Temple Place - Suite 330, 
/* Boston, MA  02111-1307 USA
/*
/**************************************************************************/

import java.io.BufferedWriter;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.io.Reader;
import java.io.Serializable;
import java.io.StreamTokenizer;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.StringTokenizer;
import java.util.Vector;
import java.util.Date;
import java.text.SimpleDateFormat;
import java.math.BigDecimal;

/**
 * Anything.
 */
public class Anything_old extends Object implements Serializable {

  static final long serialVersionUID = 2; // its the 2nd version

  public static final int eNull = 0;
  public static final int eLong = 1;
  public static final int eDouble = 2;
  public static final int eCharPtr = 3;
  public static final int eVector = 4;
  public static final int eObject = 5;
  public static final int eBool = 6;
  public static final int eBigDec = 7;
  public static final int eDate = 8;

  Object fContents;
  Hashtable fDict;
  int fTag;

  public Anything_old() {
    fTag = eNull;
    fContents = null;
  }

  public Anything_old(boolean b) {
    fTag = eBool;
    fContents = new Boolean(b);
  }

  public Anything_old(long l) {
    fTag = eLong;
    fContents = new Long(l);
  }

  public Anything_old(int i) {
    fTag = eLong;
    fContents = new Long(i);
  }

  public Anything_old(double d) {
    fTag = eDouble;
    fContents = new Double(d);
  }

  public Anything_old(String s) {
    fTag = eCharPtr;
    fContents = s;
  }

  public Anything_old(Object o) {
    fTag = eObject;
    fContents = o;
  }
  
  public Anything_old(BigDecimal bd) {
    fTag = eBigDec;
    fContents = bd;
  }

  public Anything_old(Date d) {
    fTag = eDate;
    fContents = d;
  }

  public int getType() {
    return fTag;
  }

  public boolean isNull() {
    return fTag == eNull;
  }

  public boolean isEqual(Anything_old other) {
    switch (fTag) {
      case eNull:
        return other.fTag == eNull;
      case eBool:
      case eLong:
      case eDouble:
      case eCharPtr:
      case eObject:
      case eBigDec:
      case eDate:
        return fContents.equals(other.fContents);

      case eVector:
        int sz = size();
        for (int i = 0; i < sz; i++) {
          if (slotName(i) != null) {
            if (!(slotName(i).equals(other.slotName(i)))) {
              return false;
            }
          } else if (other.slotName(i) != null) {
            return false;
          }
          if (!(get(i).isEqual(other.get(i)))) {
            return false;
          }
        }
        return true;

      default:
        System.out.println("There is something wrong with this: fTag =" + fTag);
        break;
    }
    return false;
  }

  public int size() {
    switch (fTag) {
      case eNull:
        return 0;

      case eBool:
      case eLong:
      case eDouble:
      case eCharPtr:
      case eObject:
      case eBigDec:
      case eDate:
        return 1;

      case eVector:
        Vector v = (Vector) fContents;
        return v.size();

      default:
        break;
    }
    return 0;
  }

  public Enumeration elements() {
    switch (fTag) {
      case eNull:
        break;

      case eBool:
      case eLong:
      case eDouble:
      case eCharPtr:
      case eObject:
      case eBigDec:
      case eDate:
        return new AnythingEnumeration(this);

      case eVector:
        Vector v = (Vector) fContents;
        return v.elements();

      default:
        break;
    }
    return new AnythingEnumeration(null);
  }

  public Enumeration keys() {
    if (fDict != null)
      return fDict.keys();
    return new AnythingEnumeration(null);
  }

  public boolean isDefined(String key) {
    if (fDict != null)
      return fDict.containsKey(key);
    return false;
  }

  public Anything_old get(String key) {
    if (fDict != null) {
      Integer i = (Integer) fDict.get(key);
      if (i != null)
        return get(i.intValue());
    }
    Anything_old a = new Anything_old();
    put(key, a);
    return a;
  }

  public Anything_old safeGet(String key) {
    if (fDict != null) {
      Integer i = (Integer) fDict.get(key);
      if (i != null)
        return get(i.intValue());
    }
    System.out.println("Anything_old.safeget: key " + key + " not found");
    return new Anything_old();
  }

  public int findValue(String key) {
    if (fContents == null)
      return -1;
    if (fTag == eVector) {
      Vector vt = (Vector) fContents;
      int index = -1;
      for (Enumeration e = vt.elements(); e.hasMoreElements();) {
        index++;
        String s = ((Anything_old) e.nextElement()).asString("");
        if (s.equals(key))
          return index;
      }
      return -1;
    }
    return -1;
  }

  public Anything_old get(int index) {
    switch (fTag) {
      case eBool:
      case eLong:
      case eDouble:
      case eCharPtr:
      case eObject:
      case eBigDec:
      case eDate:
        if (index == 0) {
          return this;
        }
      case eNull:
        vectorize();
      case eVector:
        Vector v = (Vector) fContents;
        int oldSize = v.size();
        if (index >= oldSize) {
          v.setSize(index + 1);
          for (int i = index; i >= oldSize; i--) {
            v.setElementAt(new Anything_old(), i);
          }
        }
        Object o = null;
        try {
          o = v.elementAt(index);
        } catch (ArrayIndexOutOfBoundsException e) {}
        if (o != null)
          return (Anything_old) o;
        break;

      default:
        break;
    }

    return new Anything_old();
  }

  public Anything_old put(String key, Anything_old value) {
    int s;
    if (fDict == null)
      fDict = new Hashtable(10);
    if (fDict.containsKey(key)) {
      s = ((Integer) fDict.get(key)).intValue();
    } else {
      s = size();
      fDict.put(key, new Integer(s));
    }
    put(s, value);
    return this;
  }

  public Anything_old put(String key, String value) {
    put(key, new Anything_old(value));
    return this;
  }

  public Anything_old put(String key, boolean value) {
    put(key, new Anything_old(value));
    return this;
  }

  public Anything_old put(String key, long value) {
    put(key, new Anything_old(value));
    return this;
  }

  public Anything_old put(String key, int value) {
    put(key, new Anything_old(value));
    return this;
  }

  public Anything_old put(String key, double value) {
    put(key, new Anything_old(value));
    return this;
  }

  public Anything_old put(String key, Object value) {
    put(key, new Anything_old(value));
    return this;
  }

  public Anything_old put(String key, BigDecimal value) {
    put(key, new Anything_old(value));
    return this;
  }

  public Anything_old put(String key, Date value) {
    put(key, new Anything_old(value));
    return this;
  }

  public Anything_old put(int index, Anything_old value) {
    if (fTag != eVector) {
      vectorize();
    }
    Vector v = (Vector) fContents;
    int oldSize = v.size();
    if (index >= oldSize) {
      v.setSize(index + 1);
      for (int i = index - 1; i >= oldSize; i--) {
        v.setElementAt(new Anything_old(), i);
      }
    }
    v.setElementAt(value, index);
    return this;
  }

  private void nullify() {
    fTag = eNull;
    fContents = null;
    fDict = null;
  }

  private void vectorize() {
    Vector v = new Vector(5);
    switch (fTag) {

      case eBool:
        v.addElement(new Anything_old(((Boolean) fContents).booleanValue()));
        break;
      case eLong:
        v.addElement(new Anything_old(((Long) fContents).longValue()));
        break;
      case eDouble:
        v.addElement(new Anything_old(((Double) fContents).doubleValue()));
        break;
      case eCharPtr:
        v.addElement(new Anything_old((String) fContents));
        break;
      case eObject:
        v.addElement(new Anything_old(fContents));
        break;
      case eBigDec:
        v.addElement(new Anything_old((BigDecimal) fContents));
        break;
      case eDate:
        v.addElement(new Anything_old((Date) fContents));
        break;
      case eNull:
      case eVector:
      default:
    }
    fContents = v;
    fTag = eVector;
  }

  public Anything_old put(int index, String value) {
    put(index, new Anything_old(value));
    return this;
  }

  public Anything_old put(int index, boolean value) {
    put(index, new Anything_old(value));
    return this;
  }

  public Anything_old put(int index, long value) {
    put(index, new Anything_old(value));
    return this;
  }

  public Anything_old put(int index, int value) {
    put(index, new Anything_old(value));
    return this;
  }

  public Anything_old put(int index, double value) {
    put(index, new Anything_old(value));
    return this;
  }

  public Anything_old put(int index, Object value) {
    put(index, new Anything_old(value));
    return this;
  }

  public Anything_old put(int index, BigDecimal value) {
    put(index, new Anything_old(value));
    return this;
  }

  public Anything_old put(int index, Date value) {
    put(index, new Anything_old(value));
    return this;
  }

  public Anything_old append(Anything_old value) {
    if (fTag != eVector) {
      vectorize();
    }
    int index = size();
    Vector v = (Vector) fContents;
    v.setSize(index + 1);
    v.setElementAt(value, index);
    return this;
  }

  public Anything_old append(String value) {
    append(new Anything_old(value));
    return this;
  }

  public Anything_old append(long value) {
    append(new Anything_old(value));
    return this;
  }

  public Anything_old append(boolean value) {
    append(new Anything_old(value));
    return this;
  }

  public Anything_old append(int value) {
    append(new Anything_old(value));
    return this;
  }

  public Anything_old append(double value) {
    append(new Anything_old(value));
    return this;
  }

  public Anything_old append(Object value) {
    append(new Anything_old(value));
    return this;
  }

  public Anything_old append(BigDecimal value) {
    append(new Anything_old(value));
    return this;
  }

  public Anything_old append(Date value) {
    append(new Anything_old(value));
    return this;
  }

  public Anything_old remove(String key) {

    if (fDict != null) {
      Integer i = (Integer) fDict.remove(key);
      if (i != null) {
        Vector v = (Vector) fContents;
        v.removeElementAt(i.intValue());
        int iv = i.intValue();
        syncAfterRemove(iv);
      }
    } else {
      System.out.println("Anything_old.remove: no dict");
    }
    return this;
  }

  public Anything_old remove(int Index) {
    if (fTag == eVector && (Index >= 0 && Index < size())) {
      String slotName = slotName(Index);
      if (slotName != null) {
        remove(slotName);
      } else {
        Vector v = (Vector) fContents;
        v.removeElementAt(Index);
        syncAfterRemove(Index);
      }
    } else if (Index == 0) {
      nullify();
    } else {
      System.out.println("Anything_old.remove: " + Index + " out of bounds");
    }
    return this;
  }

  private void syncAfterRemove(int Index) {
    if (size() == 0) {
      nullify();
      return;
    }
    if (fDict == null) {
      return;
    }

    for (Enumeration e = fDict.keys(); e.hasMoreElements();) {
      String k = (String) e.nextElement();
      Integer ii = (Integer) fDict.get(k);
      if (ii.intValue() > Index) {
        fDict.put(k, new Integer(ii.intValue() - 1));
      }
    }
  }

  private void tab(PrintStream out, int cols) {
    for (int i = 0; i < cols; i++)
      out.print("  ");
  }

  private String escape(String s, boolean escSpace) {
    int len = s.length();
    StringBuffer dst = new StringBuffer(2 * len); // simple assumption to have
    // enough room

    for (int i = 0; i < len; ++i) {
      char c = s.charAt(i);
      int n = (int) c;
      if (c == '\\') {
        dst.append("\\\\");
      } else if (c == '\"') {
        dst.append("\\\"");
      } else if (c == '\'') {
        dst.append("\\\'");
      } else if (c == '\n') {
        dst.append("\\n");
      } else if (c == '\t') {
        dst.append("\\t");
      } else if (c == '\b') {
        dst.append("\\b");
      } else if (c == '\f') {
        dst.append("\\f");
      } else if (c == '\r') {
        dst.append("\\r");
      } else if (c == ' ') {
        if (escSpace) {
          dst.append("\\u0020");
        } else {
          dst.append(' ');
        }
      } else if (n > 32 && n <= 126 || n >= 160 && n <= 254) {
        dst.append(c);
      } else {
        dst.append("\\u");
        String h = Integer.toHexString(n);
        if (h.length() == 2) {
          dst.append("00");
        } else if (h.length() == 1) {
          dst.append("000");
        } else {
          dst.append('0');
        }
        dst.append(h);
      }
    }
    return dst.toString();
  }

  public String asEscapedString(String dflt) {
    switch (fTag) {
      case eBool:
      case eLong:
      case eDouble:
      case eBigDec:
      case eDate:
        return fContents.toString();
      case eObject:
      case eCharPtr:
        return escape(fContents.toString(), false);
      default:
        break;
    }
    return dflt;
  }

  public String asString(String dflt) {
    switch (fTag) {
      case eBool:
      case eLong:
      case eDouble:
      case eCharPtr:
      case eObject:
      case eBigDec:
        return fContents.toString();
      case eDate:
        return dateString(fContents);
      default:
        break;
    }
    return dflt;
  }

  public Object asObject() {
    return fContents;
  }

  public long asLong(long dflt) {
    switch (fTag) {
      case eBool:
        return (((Boolean) fContents).booleanValue() ? 1 : 0);
      case eLong:
      case eDouble:
        Number n = (Number) fContents;
        return n.longValue();
      case eBigDec:
        return ((BigDecimal) fContents).longValue();
      case eDate:
          return ((Date) fContents).getTime();
      case eCharPtr:
        long value = dflt;
        try {
          value = Long.parseLong((String) fContents);
        } catch (NumberFormatException e) {
          value = dflt;
        }
        return value;
      default:
        break;
    }
    return dflt;
  }

  public BigDecimal asBigDecimal(BigDecimal dflt) {
    switch (fTag) {
      case eBool:
        return new BigDecimal(((Boolean) fContents).booleanValue() ? 1 : 0);
      case eLong:
        Number n = (Number) fContents;
        return new BigDecimal(n.longValue());
      case eDouble:
        return new BigDecimal(((Double) fContents).toString());
      case eBigDec:
        return ((BigDecimal) fContents);
      case eDate:
          return new BigDecimal(((Date) fContents).getTime());
      case eCharPtr:
        BigDecimal value = dflt;
        try {
          value = new BigDecimal((String) fContents);
        } catch (NumberFormatException e) {
          value = dflt;
        }
        return value;
      default:
        break;
    }
    return dflt;
  }

  public BigDecimal asBigDecimal(long dflt) {
    return asBigDecimal(new BigDecimal(dflt));
  }

  public BigDecimal asBigDecimal(String dflt) {
    return asBigDecimal(new BigDecimal(dflt));
  }

  public Date asDate(Date dflt) {
    switch (fTag) {
      case eLong:
        Number n = (Number) fContents;
        return new Date(n.longValue());
      case eBigDec:
        return new Date(((BigDecimal) fContents).longValue());
      case eDate:
        return ((Date) fContents);
      case eCharPtr:
        return Anything_old.dateParse(fContents, dflt);
      default:
        break;
    }
    return dflt;
  }

  public Date asDate(String dflt) {
    return asDate(Anything_old.dateParse(dflt, (Date) null));
  }

  public Date asDate(long dflt) {
    if (dflt < 0)
      return asDate(new Date(System.currentTimeMillis()));
    else
      return asDate(new Date(dflt));
  }
  public double asDouble(double dflt) {
    switch (fTag) {
      case eBool:
        return (((Boolean) fContents).booleanValue() ? 1.0 : 0.0);
      case eLong:
      case eDouble:
        Number n = (Number) fContents;
        return n.doubleValue();
      case eBigDec:
          return ((BigDecimal) fContents).doubleValue();
      case eCharPtr:
        double value = dflt;
        try {
          value = (Double.valueOf((String) fContents)).doubleValue();
        } catch (NumberFormatException e) {
          value = dflt;
        }
        return value;
      default:
        break;
    }
    return dflt;
  }

  public boolean asBool(boolean dflt) {
    switch (fTag) {
      case eBool:
        return ((Boolean) fContents).booleanValue();
      case eCharPtr:
        String upperCased = ((String) fContents).toUpperCase();
        if (upperCased.equals("TRUE")) {
          return true;
        }
        if (upperCased.equals("FALSE")) {
          return false;
        }
        break;
      default:
        break;
    }
    return asLong((long) (dflt ? 1 : 0)) != 0;
  }

  public void save(PrintStream out) {
    Print(out, 0);
  }

  public String slotName(int ix) {
    if (fDict != null) {
      for (Enumeration e = fDict.keys(); e.hasMoreElements();) {
        String s = (String) e.nextElement();
        Integer i = (Integer) fDict.get(s);
        if (i.intValue() == ix)
          return s;
      }
    }
    return null;
  }

  public void PrintTerse(PrintWriter out) {
    switch (fTag) {
      case eNull:
        out.print("* ");
        break;

      case eBool:
      case eLong:
      case eDouble:
        out.print(fContents.toString()+" ");
        break;
 
      case eBigDec:
        out.print("BigDecimal\""+fContents.toString()+"\"");
        break;

      case eDate:
        out.print("Date\""+dateString(fContents)+"\"");
        break;

      case eCharPtr:
        out.print("\"");
        out.print(escape(fContents.toString(), false));
        out.print("\"");
        break;

      case eVector:
        Vector v = (Vector) fContents;
        out.print("{");
        for (int i = 0; i < v.size(); i++) {

          String key = slotName(i);
          if (key != null) {
            out.print("/"+escape(key, true)+" ");
          }

          Anything_old aa = (Anything_old) v.elementAt(i);
          aa.PrintTerse(out);
        }
        out.print("}");
        break;

      default:
        out.print("<oops>");
        break;
    }
  }

  public void Print(PrintStream out) {
    out.println("");
    Print(out, 0);
  }

  public void Print(PrintStream out, int cols) {
    switch (fTag) {
      case eNull:
        out.println("*");
        break;

      case eBool:
      case eLong:
      case eDouble:
        out.println(fContents.toString());
        break;

      case eBigDec:
        out.println("BigDecimal \""+fContents.toString()+"\"");
        break;

      case eDate:
        out.println("Date \""+dateString(fContents)+"\"");
        break;

      case eCharPtr:
        out.print("\"");
        out.print(asEscapedString(""));
        out.println("\"");
        break;

      case eVector:
        Vector v = (Vector) fContents;
        out.println("{");
        for (int i = 0; i < v.size(); i++) {
          tab(out, cols + 1);

          String key = slotName(i);
          if (key != null) {
            out.print("/"+escape(key, true)+" ");
          }

          Anything_old aa = (Anything_old) v.elementAt(i);
          aa.Print(out, cols + 1);
        }
        tab(out, cols);
        out.println("}");
        break;

      default:
        out.println("<oops>");
        break;
    }
  }

  private Anything_old parse1(StreamTokenizer t) {
    int tok = StreamTokenizer.TT_EOF;

    try {
      tok = t.nextToken();
    } catch (IOException e) {
      System.out.println("IOException");
    }

    switch (tok) {
      case StreamTokenizer.TT_EOF:
        break;
      case StreamTokenizer.TT_NUMBER:
        double di = java.lang.Math.rint(t.nval);
        if (di == t.nval) {
          // double is an integer
          Double d = new Double(t.nval);
          return new Anything_old(d.longValue());
        } else {
          // 'real' double
          return new Anything_old(t.nval);
        }
      case StreamTokenizer.TT_WORD:
        if (t.sval.equals("BigDecimal") || t.sval.equals("NUMBER")) {
          try {
            tok = t.nextToken();
            return new Anything_old(new BigDecimal(tok == '\"' ? t.sval : "0"));
          } catch (Exception e) {
            System.out.println("wrong token: " + tok);
            return new Anything_old();
          }
        }
        if (t.sval.equals("Date")) {
          try {
            tok = t.nextToken();
            SimpleDateFormat sd = new SimpleDateFormat(anyDateFormat);
            return new Anything_old(sd.parse(tok == '\"' ? t.sval : ""));
          } catch (Exception e) {
            System.out.println("wrong date: " + tok);
            return new Anything_old();
          }
        }
        // fall through
      case '\"':
        return new Anything_old(t.sval);
      case '*':
        break;
      case '{':
        Anything_old a = new Anything_old();
        a.parse2(t);
        return a;
      default:
        System.out.println("wrong character: " + tok);
        break;
    }
    return new Anything_old();
  }

  private void parse2(StreamTokenizer t) {
    try {
      int i;
      for (i = 0;; i++) {
        int tok = t.nextToken();
        if (tok == '}' || tok == StreamTokenizer.TT_EOF)
          break;

        String key = null;
        boolean gotKey = false;
        int index = i;

        if (tok == '/') { // read key
          tok = t.nextToken();
          if (tok == '"' || tok == StreamTokenizer.TT_WORD) {
            gotKey = true;
            key = t.sval;
          } else if (tok == StreamTokenizer.TT_NUMBER)
            index = (int) t.nval;
        } else
          t.pushBack();

        if (gotKey)
          put(key, parse1(t));
        else
          put(index, parse1(t));
      }
    } catch (IOException e) {
      System.out.println("IOException");
    }
  }

  public void load(InputStream in) {
    Reader r = new InputStreamReader(in);
    load(r);
  }

  public void load(Reader r) {
    StreamTokenizer t = new StreamTokenizer(r);

    t.slashSlashComments(true);

    t.wordChars('_', '_');

    t.commentChar('#');

    t.ordinaryChar('{');
    t.ordinaryChar('}');
    t.ordinaryChar('/'); // key
    t.ordinaryChar('*'); // null

    t.parseNumbers(); // cannot be switched of, is turned on by default
    t.quoteChar('\"');

    Anything_old a = parse1(t);
    fTag = a.fTag;
    fContents = a.fContents;
    fDict = a.fDict;

  }

  public static Anything_old create(String s) {
    StringReader reader = new StringReader(s);
    return Anything_old.read(reader);
  }

  public static Anything_old read(Reader in) {
    Anything_old any = new Anything_old();
    if (in != null)
      any.load(in);
    return any;
  }

  public static Anything_old read(InputStream in) {
    Anything_old any = new Anything_old();
    if (in != null)
      any.load(in);
    return any;
  }

  public static Anything_old read(String filename) {
    InputStream in = null;
    try {
      in = new FileInputStream(filename);
      return read(in);
    } catch (FileNotFoundException e) {
      System.out.println("File " + filename + " not found");
    }
    return new Anything_old();
  }

  public void write(String filename) {
    PrintStream out = null;
    try {
      out = new PrintStream(new FileOutputStream(filename));
      save(out);
    } catch (FileNotFoundException e) {
      System.out.println("File " + filename + " not found");
    }
  }

  public Anything_old deepClone() {
    byte buffer[] = null;
    try {
      ByteArrayOutputStream out = new ByteArrayOutputStream();
      save(new PrintStream(out));
      buffer = out.toByteArray();
      ByteArrayInputStream in = new ByteArrayInputStream(buffer);
      return Anything_old.read(in);
    } catch (Exception e) {
      System.out.println("DeepClone Exception");
    }
    return new Anything_old();
  }

  public Anything_old LookupPath(String path, String delim) {
    StringTokenizer st = new StringTokenizer(path, delim);
    Anything_old c;
    String s;

    c = this;
    while (st.hasMoreElements()) {
      s = st.nextToken();
      if (s.matches("[0-9]+")) {
        try {
          int i = new Integer(s.toString()).intValue();
          c = c.get(i);
          continue;
        } catch (NumberFormatException e) {}
        // fall through
      }
      if (!c.isDefined(s))
        return null;
      c = c.get(s);
    }
    return c;
  }
  
  public Anything_old at(String path) {
    Anything_old res = LookupPath(path, "/");
    return res == null ? new Anything_old() : res;
  }

  @Override
  public String toString() {
    StringWriter strwr = new StringWriter();
    PrintTerse(new PrintWriter(strwr));
    return new String(strwr.getBuffer());
  }
  
  public static final String anyDateFormat = "yyyy-MM-dd HH:mm:ss.S";

  private static String dateString(Object o) {
    SimpleDateFormat df = new SimpleDateFormat(anyDateFormat);
    return df.format((Date) o);
  }
  
  private static Date dateParse(Object d, Date dflt) {
    Date value = null;
    SimpleDateFormat df = new SimpleDateFormat(anyDateFormat);
    try {
      value = df.parse((String) d);
    } catch (Exception e) {
      value = dflt;
    }
    return value;
  }
  
	public class AnythingEnumeration implements Enumeration {

		Object fObject;

		AnythingEnumeration(Object object) {
			fObject = object;
		}

		public boolean hasMoreElements() {
			return fObject != null;
		}

		public Object nextElement() {
			Object o = fObject;
			fObject = null;
			// if (o == null)
			// throw new java.util.NoSuchElementException();
			return o;
		}
	}
  
	public static void main(String[] args) {
		Anything_old any = Anything_old.create("{ /key value freistehend \"mit line \\n break\" }");
		any.Print(System.out);
	}
	
  
}

